﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Kindohm.KSynth.Library;

namespace Kindohm.KSynth.UI
{
    public partial class WaveFormEditSurface : UserControl
    {
        List<WaveFormPoint> points;
        WaveFormPoint movingPoint;

        public WaveFormEditSurface()
        {
            InitializeComponent();
            this.drawingCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(drawingCanvas_MouseLeftButtonDown);
            this.drawingCanvas.MouseLeftButtonUp += new MouseButtonEventHandler(drawingCanvas_MouseLeftButtonUp);
            this.drawingCanvas.MouseMove += new MouseEventHandler(drawingCanvas_MouseMove);
            this.Loaded += new RoutedEventHandler(WaveFormEditor_Loaded);
            this.Reset();
        }

        public void Reset()
        {
            this.drawingCanvas.Children.Clear();
            this.movingPoint = null;
            this.points = new List<WaveFormPoint>();

            WaveFormPoint startPoint = new WaveFormPoint();
            startPoint.Canvas = this.drawingCanvas;
            startPoint.Movable = false;
            startPoint.MinX = 0;
            startPoint.MaxX = 0;
            startPoint.Ellipse = this.GetEllipse();
            this.drawingCanvas.Children.Add(startPoint.Ellipse);
            startPoint.Point = new Point(0, this.drawingCanvas.Height / 2);

            WaveFormPoint endPoint = new WaveFormPoint();
            endPoint.Canvas = this.drawingCanvas;
            endPoint.Movable = false;
            endPoint.MinX = this.drawingCanvas.Width;
            endPoint.MaxX = this.drawingCanvas.Width;
            endPoint.Ellipse = this.GetEllipse();
            this.drawingCanvas.Children.Add(endPoint.Ellipse);
            endPoint.Point = new Point(this.drawingCanvas.Width,
                this.drawingCanvas.Height / 2);
            this.points.Add(startPoint);
            this.points.Add(endPoint);

            startPoint.RegisterConnection(endPoint);
        
        }

        void drawingCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.movingPoint != null)
            {
                double newX;
                double newY;
                Point mousePoint = e.GetPosition(this.drawingCanvas);

                if (mousePoint.Y < this.movingPoint.MaxY
                    & mousePoint.Y > this.movingPoint.MinY)
                {
                    newY = mousePoint.Y;
                }
                else
                    newY = this.movingPoint.Point.Y;

                if (mousePoint.X < this.movingPoint.MaxX
                    & mousePoint.X > this.movingPoint.MinX)
                {
                    newX = mousePoint.X;
                }
                else
                    newX = this.movingPoint.Point.X;

                this.movingPoint.Point = new Point(newX, newY);
            }
        }

        void drawingCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            this.movingPoint.Ellipse.ReleaseMouseCapture();
            this.movingPoint = null;
            this.OnChanged();
        }

        void drawingCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (this.movingPoint != null)
                return;

            WaveFormPoint newPoint = new WaveFormPoint();
            newPoint.Canvas = this.drawingCanvas;
            Point point = e.GetPosition(this.drawingCanvas);
            newPoint.Ellipse = this.GetEllipse();
            this.drawingCanvas.Children.Add(newPoint.Ellipse);
            newPoint.Point = point;
            newPoint.Movable = true;
            newPoint.MinY = 0;
            newPoint.MaxY = this.drawingCanvas.Height;

            //find nearest point to the right and left
            double nearestMin = double.MinValue;
            double nearestMax = double.MaxValue;
            WaveFormPoint nearestMinPoint = null;
            WaveFormPoint nearestMaxPoint = null;

            foreach (WaveFormPoint item in this.points)
            {
                if (item.Point.X < newPoint.Point.X
                    & item.Point.X > nearestMin)
                {
                    nearestMin = item.Point.X;
                    nearestMinPoint = item;
                }

                if (item.Point.X > newPoint.Point.X
                    & item.Point.X < nearestMax)
                {
                    nearestMax = item.Point.X;
                    nearestMaxPoint = item;
                }

            }
            newPoint.MinX = nearestMin;
            newPoint.MaxX = nearestMax;

            nearestMinPoint.UnregisterConnection(nearestMaxPoint);

            newPoint.RegisterConnection(nearestMinPoint);
            newPoint.RegisterConnection(nearestMaxPoint);

            this.movingPoint = newPoint;

            this.points.Add(newPoint);
            this.OnChanged();
        }

        void WaveFormEditor_Loaded(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        Ellipse GetEllipse()
        {
            Ellipse ellipse = new Ellipse();
            ellipse.Width = 10;
            ellipse.Height = 10;
            ellipse.Fill = new SolidColorBrush(Colors.Red);
            ellipse.Stroke = new SolidColorBrush(Colors.Red);
            TranslateTransform trans = new TranslateTransform();
            trans.X = -5;
            trans.Y = -5;
            ellipse.RenderTransform = trans;
            ellipse.MouseLeftButtonDown += new MouseButtonEventHandler(ellipse_MouseLeftButtonDown);
            return ellipse;
        }

        void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Ellipse ellipse = (Ellipse)sender;
            ellipse.CaptureMouse();
            foreach (WaveFormPoint point in this.points)
            {
                if (point.Movable && point.Ellipse == ellipse)
                {
                    this.movingPoint = point;
                    return;
                }
            }
            this.OnChanged();
        }

        void OnChanged()
        {
            if (this.Changed != null)
                this.Changed(this, EventArgs.Empty);
        }

        //public CustomWaveForm GetCustomWaveformData()
        //{
        //    WaveFormPointComparer comparer = new WaveFormPointComparer();
        //    this.points.Sort(comparer);

        //    //x values on waveform must be converted to
        //    //fit ushort.MaxValue
        //    CustomWaveForm customWaveForm = new CustomWaveForm();

        //    for (int i = 0; i < this.points.Count - 1; i++)
        //    {
        //        double halfHeight = this.drawingCanvas.Height / 2;
        //        WaveFormPoint point = this.points[i];
        //        WaveFormPoint nextPoint = this.points[i + 1];
        //        WaveFormChunk chunk = new WaveFormChunk();
        //        double xRatio = point.Point.X / this.drawingCanvas.Width;
        //        double xEndRatio = nextPoint.Point.X / this.drawingCanvas.Width;
        //        ushort chunkStart = (ushort)(xRatio * (double)ushort.MaxValue);
        //        ushort chunkEnd = (ushort)(xEndRatio * (double)ushort.MaxValue);

        //        double yRatio = (point.Point.Y - halfHeight) / halfHeight;
        //        double yEndRatio = (nextPoint.Point.Y - halfHeight) / halfHeight;
        //        short yStart = (short)(yRatio * (double)short.MaxValue);
        //        short yEnd = (short)(yEndRatio * (double)short.MaxValue);
        //        int rise = (int)(yEnd - yStart);

        //        double slope = ((double)rise / (double)(chunkEnd - chunkStart));
        //        chunk.Slope = slope;
        //        chunk.B = yStart;
        //        chunk.StartPhase = chunkStart;
        //        chunk.EndPhase = chunkEnd;

        //        customWaveForm.Chunks.Add(chunk);

        //    }

        //    return customWaveForm;


        //}

        //public WriteableBitmap GetWaveImage()
        //{
        //    WriteableBitmap bitmap = new WriteableBitmap(this.drawingCanvas, null);
        //    return bitmap;
        //}

        public event EventHandler Changed;


    }
}
